home *** CD-ROM | disk | FTP | other *** search
- /*
- File: ODMath.cpp
-
- Contains: Math routines (fixed-point and wide) for OpenDoc.
-
- Owned by: Jens Alfke
- Written by: Cary Clark, Georgiann Delaney, Michael Fairman, Dave Good,
- Robert Johnson, Keith McGreggor, Oliver Steele, David Van Brink,
- Chris Yerga
-
- Copyright: © 1987 - 1995 by Apple Computer, Inc., all rights reserved.
-
- Notes:
- The PowerPC definitions of many of these functions are already built
- into the Mac OS, so they are compiled here only for 68k. Likewise,
- the 68k definitions of some of these functions are coded in assembly
- language in ODMathM.a, and they are compiled here only for PowerPC.
-
- To Do:
- In Progress:
-
- */
-
-
- #ifndef _ODMATH_
- #include "ODMath.h"
- #endif
-
- #ifndef __FIXMATH__
- #include <FixMath.h>
- #endif
-
-
- //=============================================================================
- // Constants
- //=============================================================================
-
-
- #define longSize 32
- #define wideSize 64
-
- #define highBit ((ODULong) 0x80000000)
-
-
- //=============================================================================
- // Wide Math For Non-PowerPC
- //=============================================================================
-
-
- #if !defined(powerc) && !defined(__powerc)
-
- #ifdef __MWERKS__
- #if 0
- extern asm short ODFirstBit(long x)
- {
- machine 68020
- move.l (sp)+,a0 // get return address
- move.l (sp),d0 // get x
- bfffo d0{0:0},d1
- moveq #31,d0
- sub.w d1,d0
- addq.l #4,sp
- jmp (a0)
- }
- #endif
-
- extern asm ODSLong ODWideDivide(const ODWide *dividend,
- ODSLong divisor, ODSLong *remainder)
- {
- machine 68020
- machine 68881
- link a6,#-2
- moveq #-1,d0
- cmp.l 16(a6),d0 // if (rem == (void *)-1)
- seq -1(a6) // set check
- bne.s @noCheck
- clr.l 16(a6) // rem = 0
- @noCheck:
- move.l 8(a6),a0 // get num
- move.l (a0)+,d1
- move.l (a0),d0
- move.l 12(a6),d2 // get denom
- beq.s @div0
- bpl.s @1
- neg.l d2
- @1: tst.l 16(a6) // check rem
- bne.s @3
- lsr.l #1,d2
- tst.l d1
- bpl.s @2
- neg.l d2
- @2: add.l d2,d0
- bfexts d2{0:1},d2
- addx.l d2,d1
- @3: divs.l 12(a6),d1:d0
- bvc.s @ok
- move.l 12(a6),d2
- @div0: tst.b -1(a6) // check check
- bne.s @div1
- eor.l d1,d2
- bmi.s @div1
- move.l #0x7FFFFFFF,d0
- bra.s @div2
- @div1: move.l #0x80000000,d0
- @div2: move.l #0x80000000,d1
- @ok: move.l 16(a6),d2 // get rem
- beq.s @done
- move.l d2,a0
- move.l d1,(a0)
- @done: unlk a6
- rtd #12
- }
-
- extern asm ODULong ODWideSquareRoot( const ODWide *src )
- {
- machine 68020
- machine 68881
- move.l (sp)+,a0
- move.l #0x80000000,d1
-
- // fmove.l d1,fp1
- opword 0xF201, 0x4080
-
- move.l (sp),a1 // Get src
- move.l (a1)+,d0 // Get hi long
- add.l d1,d0 // Offset for sign
-
- // fmove.l d0,fp0 // Move to FP0
- opword 0xF200, 0x4000
-
- // fsub.x fp1,fp0 // Compensate for offset
- opword 0xF200, 0x0428
-
- // fscale.w #32,fp0 // Shift by 32
- opword 0xF23C, 0x5026, 0x0020
-
- move.l (a1),d0 // Get lo long
- add.l d1,d0 // Offset for sign
-
- // fadd.l d0,fp0 // Add to FP0
- opword 0xF200, 0x4022
-
- // fsub.x fp1,fp0 // Compensate for offset
- opword 0xF200, 0x0428
-
- // fsqrt.x fp0 // The whole point
- opword 0xF200, 0x0004
-
- // fadd.x fp1,fp0 // Offset for sign
- opword 0xF200, 0x0422
-
- // fmove.l fp0,d0 // Pass result to D0
- opword 0xF200, 0x6000
-
- sub.l d1,d0 // Compensate for offset
- addq.l #4,sp
- jmp (a0)
- }
-
-
-
-
-
- #endif
-
-
-
- ODFixed lastSinCosAngle = 0; // Globals used in .a file
- ODFract lastSine = 0,
- lastCosine = kODFract1;
-
-
- // Wide math routines are already in the OS on Power Macs.
-
-
- ODSShort ODWideCompare(const ODWide *a, const ODWide *b)
- {
- if (a->hi > b->hi) return 1;
- if (a->hi < b->hi) return -1;
- if (a->lo > b->lo) return 1;
- if (a->lo < b->lo) return -1;
- return 0;
- }
-
-
- ODWide *
- ODWideNegate(register ODWide *dst)
- {
- if (dst->lo) {
- dst->lo = -dst->lo;
- dst->hi = ~dst->hi;
- } else
- dst->hi = -dst->hi;
- return dst;
- }
-
-
- /* Shift a ODWide to the right (shift > 0) or left (shift < 0) */
- ODWide *
- ODWideShift(register ODWide *src, register ODSShort shift)
- {
- register long x = src->hi, y = src->lo;
- if (shift > 0)
- if (shift >= longSize)
- { src->hi = -(x < 0);
- src->lo = x >> shift - longSize;
- if (shift == longSize && y < 0 || x << wideSize - shift < 0)
- ++src->lo || ++src->hi;
- }
- else
- { src->hi = x >> shift;
- src->lo = x << longSize - shift | (unsigned long)y >> shift;
- if (y << longSize - shift < 0)
- ++src->lo || ++src->hi;
- }
- else if ( (shift = -shift) != 0 )
- if (shift >= longSize)
- { src->hi = y << shift - longSize;
- src->lo = 0;
- }
- else
- { src->hi = x << shift | (unsigned long)y >> longSize - shift;
- src->lo = y << shift;
- }
- return src;
- }
-
-
- ODWide *
- ODWideAdd(register ODWide *dst, register const ODWide *src)
- {
- dst->lo += src->lo;
- if (dst->lo < src->lo)
- dst->hi += src->hi + 1;
- else
- dst->hi += src->hi;
- return dst;
- }
-
-
- ODWide *
- ODWideSubtract(register ODWide *dst, register const ODWide *src)
- {
- if (dst->lo < src->lo)
- dst->hi -= src->hi + 1;
- else
- dst->hi -= src->hi;
- dst->lo -= src->lo;
- return dst;
- }
-
-
- // ODWideMultiply and ODWideDivide are in ODMathM.a
-
-
-
- //=============================================================================
- // Wide Math & Bit-Twiddling For PowerPC
- //=============================================================================
-
-
- #else /*powerc*/
-
-
- ODSShort
- ODFirstBit( ODSLong x ) // JPA: I wrote this from scratch
- {
- ODSShort bit = 0;
-
- if (x == 0)
- return -1;
-
- if (x >= 1UL << 16)
- bit += 16, x >>= 16;
- if (x >= 1UL << 8)
- bit += 8, x >>= 8;
- if (x >= 1UL << 4)
- bit += 4, x >>= 4;
- if (x >= 1UL << 2)
- bit += 2, x >>= 2;
- if (x >= 1UL << 1)
- bit += 1;
- return bit;
- }
-
- #undef ODWideCompare
- ODSShort ODWideCompare(const ODWide *a, const ODWide *b)
- {
- return (ODSShort) WideCompare(a,b);
- }
-
- #undef ODWideNegate
- ODWide * ODWideNegate(register ODWide *dst)
- {
- return (ODWide*) WideNegate(dst);
- }
-
- #undef ODWideShift
- ODWide * ODWideShift(register ODWide *src, register ODSShort shift)
- {
- return (ODWide*) WideShift(src,(long)shift);
- }
-
- #undef ODWideAdd
- ODWide * ODWideAdd(register ODWide *dst, register const ODWide *src)
- {
- return (ODWide*) WideAdd(dst,src);
- }
-
- #undef ODWideSubtract
- ODWide * ODWideSubtract(register ODWide *dst, register const ODWide *src)
- {
- return (ODWide*) WideSubtract(dst,src);
- }
-
- #undef ODWideDivide
- ODSLong ODWideDivide( register const ODWide *dividend,
- ODSLong divisor, ODSLong *remainder)
- {
- return (ODSLong) WideDivide(dividend,divisor,remainder);
- }
-
- #undef ODWideSquareRoot
- ODULong ODWideSquareRoot(register const ODWide *src)
- {
- return (ODULong) WideSquareRoot(src);
- }
-
- ODFract
- ODFractSinCos( ODFixed angle, ODFract *cos )
- {
- // I have no idea whether FracSin and FracCos are native ... if not,
- // this will be much slower than it could be. But is this every going
- // to be a bottleneck? [OPTIMIZATION]
-
- if( cos )
- *cos = FracCos(angle);
- return FracSin(angle);
- }
-
- #endif /*powerc*/
-